package edu.nyu.hps.assignment10;

public class Moves {
	int[] constraints;
	int[][] board;
	Cell[][] myBoard;
	int bestScore = 1000;
	Cell bestCell = null;

	public Moves(Cell[][] myBoard, int[] constraints, int[][] board) {
		this.constraints = constraints;
		this.myBoard = myBoard;
		this.board = board;
	}

	void makeMove() {
		if (constraints[0] != -1) {
			rowConstraint(constraints[0]);
		} else if (constraints[1] != -1) {
			columnConstraint(constraints[1]);
		} else {
			noConstraint();
		}
	}

	String returnMove() {
		makeMove();
		return "SET:" + bestCell.x + "," + bestCell.y + "," +bestCell.bestValue;
	}
	
	int returnScore() {
		makeMove();
		return bestScore;
	}
	
	private void columnConstraint(int j) {
		Cell bestCell = null;
		int bestCount = 1000;
		for (int i = 0; i < 9; i++) {
			Cell c = myBoard[i][j];
			if (!c.taken) {
				int myCount = getScoreFor(c);
				if (myCount < bestCount) {
					bestCount = myCount;
					bestCell = c;
				}
			}
		}
//		if (bestCell != null) {
			this.bestCell = bestCell;
			this.bestScore = bestCount;
//			return "SET:" + bestCell.x + "," + bestCell.y + ","
//					+ bestCell.bestValue;
//		}
//		return null;
	}

	private void rowConstraint(int i) {
		Cell bestCell = null;
		int bestCount = 1000;
		for (int j = 0; j < 9; j++) {
			Cell c = myBoard[i][j];
			if (!c.taken) {
				int myCount = getScoreFor(c);
				if (myCount < bestCount) {
					bestCount = myCount;
					bestCell = c;
				}
			}
		}
//		if (bestCell != null) {
			this.bestCell = bestCell;
			this.bestScore = bestCount;
//			return "SET:" + bestCell.x + "," + bestCell.y + ","
//					+ bestCell.bestValue;
//		}
//		return null;
	}

	private void noConstraint() {
		Cell bestCell = null;
		int bestCount = 1000;
		for (int i = 0; i < 9; i++) {
			for (int j = 0; j < 9; j++) {
				Cell c = myBoard[i][i];
				if (!c.taken) {
					int myCount = getScoreFor(c);
					if (myCount < bestCount) {
						bestCount = myCount;
						bestCell = c;
					}
				}
			}
		}
//		if (bestCell != null) {
			this.bestCell = bestCell;
			this.bestScore = bestCount;
//			return "SET:" + bestCell.x + "," + bestCell.y + ","
//					+ bestCell.bestValue;
//		}
//		return null;
	}

	private int getScoreFor(Cell c) {
		int bestVal = 0, bestCount = 1000;
		for (int k = 0; k < c.possibilities.size(); k++) {
			int val = c.possibilities.get(k);
			int[] oppConstraints = new int[2];
			if ((constraints[0] == -1 && constraints[1] == -1)
					|| (constraints[0] != -1 && constraints[1] == -1)) {
				oppConstraints[0] = -1;
				oppConstraints[1] = c.y;
			} else if (constraints[0] == -1 && constraints[1] != -1) {
				oppConstraints[0] = c.x;
				oppConstraints[1] = -1;
			}
			int myCount = getScoreForCellAndValue(c, val, oppConstraints);

			if (myCount < bestCount) {
				bestVal = val;
				bestCount = myCount;
			}
		}
		c.bestValue = bestVal;
		return bestCount;
	}

	private int getScoreForCellAndValue(Cell c, int val, int[] oppConstraints) {
		Sudoku newGame = new Sudoku();
		newGame.board = board.clone();
		newGame.board[c.x][c.y] = val;
		newGame.constraints = oppConstraints.clone();
		newGame.setBoardValues(newGame.board, newGame.myBoard);
		int count = newGame.getPossibleValues();

		return count;
	}

	void makeTree(Node n) {
		Sudoku myGame = new Sudoku();
		myGame.board = board;
		myGame.constraints = constraints;
		// /?????????????????????????????????????????????
	}
}
